static struct option options[] = {
{ "domid", 1, NULL, 'd' },
{ "title", 1, NULL, 't' },
+ { NULL }
};
int main(int argc, char **argv)
int do_quit = 0;
int opt;
char *endp;
+ int retval;
while ((opt = getopt_long(argc, argv, "d:t:", options,
NULL)) != -1) {
case 't':
title = strdup(optarg);
break;
+ case '?':
+ exit(1);
}
}
if (optind != argc) {
if (do_quit)
break;
- xenfb_poll(xenfb, &readfds);
+ retval = xenfb_poll(xenfb, &readfds);
+ if (retval == -2)
+ xenfb_teardown(xenfb);
+ if (retval < 0)
+ break;
}
xenfb_delete(xenfb);
{ "title", 1, NULL, 't' },
{ "unused", 0, NULL, 'u' },
{ "listen", 1, NULL, 'l' },
+ { NULL }
};
int main(int argc, char **argv)
int nfds;
char portstr[10];
char *endp;
+ int r;
while ((opt = getopt_long(argc, argv, "d:p:t:u", options,
NULL)) != -1) {
case 'l':
listen = strdup(optarg);
break;
+ case '?':
+ exit(1);
}
}
if (optind != argc) {
break;
}
- xenfb_poll(xenfb, &readfds);
+ r = xenfb_poll(xenfb, &readfds);
+ if (r == -2)
+ xenfb_teardown(xenfb);
+ if (r < 0)
+ break;
}
rfbScreenCleanup(server);
return NULL;
}
+/* Remove the backend area in xenbus since the framebuffer really is
+ going away. */
+void xenfb_teardown(struct xenfb *xenfb_pub)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+
+ xs_rm(xenfb->xsh, XBT_NULL, xenfb->fb.nodename);
+ xs_rm(xenfb->xsh, XBT_NULL, xenfb->kbd.nodename);
+}
+
+
void xenfb_delete(struct xenfb *xenfb_pub)
{
struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
}
-static void xenfb_on_state_change(struct xenfb_device *dev)
+static int xenfb_on_state_change(struct xenfb_device *dev)
{
enum xenbus_state state;
switch (state) {
case XenbusStateUnknown:
+ /* There was an error reading the frontend state. The
+ domain has probably gone away; in any case, there's
+ not much point in us continuing. */
+ return -1;
case XenbusStateInitialising:
case XenbusStateInitWait:
case XenbusStateInitialised:
xs_unwatch(dev->xenfb->xsh, dev->otherend, "");
xenfb_switch_state(dev, state);
}
+ return 0;
}
+/* Returns 0 normally, -1 on error, or -2 if the domain went away. */
int xenfb_poll(struct xenfb *xenfb_pub, fd_set *readfds)
{
struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
evtchn_port_t port;
unsigned dummy;
char **vec;
+ int r;
if (FD_ISSET(xc_evtchn_fd(xenfb->evt_xch), readfds)) {
port = xc_evtchn_pending(xenfb->evt_xch);
if (FD_ISSET(xs_fileno(xenfb->xsh), readfds)) {
vec = xs_read_watch(xenfb->xsh, &dummy);
free(vec);
- xenfb_on_state_change(&xenfb->fb);
- xenfb_on_state_change(&xenfb->kbd);
+ r = xenfb_on_state_change(&xenfb->fb);
+ if (r == 0)
+ r = xenfb_on_state_change(&xenfb->kbd);
+ if (r == -1)
+ return -2;
}
return 0;